<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title> | 俊樹&#39;s Miscellaneous</title>

    
<link href="/favicon/favicon.ico" rel="shortcut icon" type="image/x-icon" />




<meta name="author" content="安田俊樹" />
<meta name="description" content="333 * {margin:0; padding:0}body {background:black; text-align:center}h1 {font-size:12px; color:gray; font-weight:normal; line-height:200%}h1 .sub {vertical-align:super; color:red; font-size:9px; }.info {position:absolute; right:0}#table {position:relative; width:800px; margin:20px auto 10px; height:544px; background:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/table.jpg) no-repeat}.ball {position:absolute; width:30px; height:30px}#dotWrap {position:absolute; z-index:2; left:32px; top:32px; width:736px; height:480px}.guide {z-index:3; background-image:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/dashed_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=&#39;true&#39;, sizingMethod=&#39;scale&#39;, src=&#34;//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/dashed_ball.png&#34;); background-repeat:no-repeat}.target {left:500px; top:250px; background-image:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/yellow_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=&#39;true&#39;, sizingMethod=&#39;scale&#39;, src=&#34;//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/yellow_ball.png&#34;); background-repeat:no-repeat}.cue {background-image:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/white_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=&#39;true&#39;, sizingMethod=&#39;scale&#39;, src=&#34;//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/white_ball.png&#34;); background-repeat:no-repeat}.bot {position:relative; width:800px; margin:10px auto 10px; height:70px}." />



<meta name="generator" content="Hugo 0.81.0" />

<link rel="canonical" href="https://AShao0425.github.io/posts/billiard/" />


<meta property="og:title" content="" />
<meta property="og:description" content="333 * {margin:0; padding:0}body {background:black; text-align:center}h1 {font-size:12px; color:gray; font-weight:normal; line-height:200%}h1 .sub {vertical-align:super; color:red; font-size:9px; }.info {position:absolute; right:0}#table {position:relative; width:800px; margin:20px auto 10px; height:544px; background:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/table.jpg) no-repeat}.ball {position:absolute; width:30px; height:30px}#dotWrap {position:absolute; z-index:2; left:32px; top:32px; width:736px; height:480px}.guide {z-index:3; background-image:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/dashed_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=&#39;true&#39;, sizingMethod=&#39;scale&#39;, src=&#34;//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/dashed_ball.png&#34;); background-repeat:no-repeat}.target {left:500px; top:250px; background-image:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/yellow_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=&#39;true&#39;, sizingMethod=&#39;scale&#39;, src=&#34;//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/yellow_ball.png&#34;); background-repeat:no-repeat}.cue {background-image:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/white_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=&#39;true&#39;, sizingMethod=&#39;scale&#39;, src=&#34;//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/white_ball.png&#34;); background-repeat:no-repeat}.bot {position:relative; width:800px; margin:10px auto 10px; height:70px}." />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://AShao0425.github.io/posts/billiard/" /><meta property="article:section" content="posts" />






<meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content=""/>
<meta name="twitter:description" content="333 * {margin:0; padding:0}body {background:black; text-align:center}h1 {font-size:12px; color:gray; font-weight:normal; line-height:200%}h1 .sub {vertical-align:super; color:red; font-size:9px; }.info {position:absolute; right:0}#table {position:relative; width:800px; margin:20px auto 10px; height:544px; background:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/table.jpg) no-repeat}.ball {position:absolute; width:30px; height:30px}#dotWrap {position:absolute; z-index:2; left:32px; top:32px; width:736px; height:480px}.guide {z-index:3; background-image:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/dashed_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=&#39;true&#39;, sizingMethod=&#39;scale&#39;, src=&#34;//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/dashed_ball.png&#34;); background-repeat:no-repeat}.target {left:500px; top:250px; background-image:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/yellow_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=&#39;true&#39;, sizingMethod=&#39;scale&#39;, src=&#34;//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/yellow_ball.png&#34;); background-repeat:no-repeat}.cue {background-image:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/white_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=&#39;true&#39;, sizingMethod=&#39;scale&#39;, src=&#34;//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/white_ball.png&#34;); background-repeat:no-repeat}.bot {position:relative; width:800px; margin:10px auto 10px; height:70px}."/>


<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css">
<link rel="stylesheet" href="/css/icomoon.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/overlayscrollbars@1.13.1/css/OverlayScrollbars.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4.0.0/github-markdown.min.css">
<link rel="stylesheet" href="/css/site.css" />

<style>
  .ui.header a:not(.item, .ui.button):hover {
    text-decoration: underline;
  }

  
  a:not(.item, .ui.button) {
    color: seagreen !important;
  }
  

  
  .inverted a:not(.item, .ui.button) {
     color: darkseagreen !important;
  }
  

  
  body.default {
    
    background-color: ZgotmplZ;
    

    
    background-image: url(/background/back1.png);
    
  }
  

  
  body.dark {
    
    background-color: ZgotmplZ;
    

    
    background-image: url(/background/BackgroundBlack.jpg);
    
  }
  
</style>


<script>
  document.addEventListener('visibilitychange',function(){
      if( document.visibilityState == 'hidden' ){
      normal_title = document.title;
      document.title = 'w(ﾟДﾟ)w Ugh, site crashed！';
      }else{
      document.title = '(/▽＼) Yay, Site got fixed！';
      setTimeout(function(){
          document.title = normal_title;
      }, 1200)
      }
  });
</script>


<script src="/js/pace.min.js"></script>
<link href="/css/pace-theme-flash.css" rel="stylesheet">

    



<link rel="stylesheet" data-highlight href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/tomorrow.min.css" />







    
    <link rel="stylesheet" href="/css/custom.css" />
    
	
	
    <link rel="stylesheet" href="/live2d/css/live2d.css" />
  </head>

  <body class="default">
    
<nav class="ui secondary menu dream-menu dream-nav">

  <a class="item dream-flip-toggle" title="Flip it!">
    <i class="large link bullseye icon"></i>
  </a>
  <a class="item" href="https://AShao0425.github.io/" title="Home">
    <i class="large link home icon"></i>
  </a>
  
  <a class="item" onclick="themeSwitch(event)">
    <i class="large link icon theme-switch"></i>
  </a>
  
  
  <a class="item" title="Search" onclick="toggleSearch(event)">
    <i class="large link search icon"></i>
  </a>
  
</nav>

    <div class="flip-container">
      <div class="flipper">
        <section class="front">
          <div class="dream-max-width">
            
<div class="ui relaxed centered grid dream-grid dream-grid-single">
  
  
  
  

  
  <div class="sixteen wide mobile sixteen wide tablet ten wide computer column markdown-body dream-single" id="dream-save-post-as-img">
    <section class="ui top attached segment">
      <header>
        <h1 class="ui large header"><span class="sub header">
            <span class="left">
              @
              
                安田俊樹
              

              | 
                  <span data-format="luxon">0001-01-01T00:00:00Z</span>
                

              | 3 minutes read

              
              | Update at
                
                  <span data-format="luxon">0001-01-01T00:00:00Z</span>
                
              
            </span>

            
            <span class="dream-share">
  <a href="#" class="save-as-image" title="Save as image" onclick="savePostAsImg()">
    <i class="save icon"></i>
  </a>
  <a href="https://twitter.com/intent/tweet?text=&url=https%3a%2f%2fAShao0425.github.io%2fposts%2fbilliard%2f" title="Twitter">
    <i class="twitter icon"></i>
  </a>
  <a href="https://facebook.com/sharer/sharer.php?u=https%3a%2f%2fAShao0425.github.io%2fposts%2fbilliard%2f" title="Facebook">
    <i class="facebook icon"></i>
  </a>
</span>

            
          </span>
        </h1>
      </header>

      <article class="main">
        

        <h1 id="333">333</h1>
<style>
        * {margin:0; padding:0}
    body {background:black; text-align:center}
    h1 {font-size:12px; color:gray; font-weight:normal; line-height:200%}
    h1 .sub {vertical-align:super; color:red; font-size:9px; }
    .info {position:absolute; right:0}
    #table {position:relative; width:800px; margin:20px auto 10px; height:544px; background:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/table.jpg) no-repeat}
    .ball {position:absolute; width:30px; height:30px}
    #dotWrap {position:absolute; z-index:2; left:32px; top:32px; width:736px; height:480px}
    .guide {z-index:3; background-image:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/dashed_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', sizingMethod='scale', src="//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/dashed_ball.png"); background-repeat:no-repeat}
    .target {left:500px; top:250px; background-image:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/yellow_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', sizingMethod='scale', src="//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/yellow_ball.png"); background-repeat:no-repeat}
    .cue {background-image:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/white_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', sizingMethod='scale', src="//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/white_ball.png"); background-repeat:no-repeat}
    .bot {position:relative; width:800px; margin:10px auto 10px; height:70px}
    .ctrl {position:absolute; top:0; right:0; width:200px; height:80px; background:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/bg_controler.png) no-repeat}
    #force {position:absolute; left:0; top:18px; width:75px; height:20px; background:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/force_conver.png) no-repeat}
    #shootPos {position:absolute; top:0; right:14px; width:52px; height:52px}
    #dot {position:absolute; top:22px; left:22px; width:8px; height:8px; background:url(//repo.bfw.wiki/bfwrepo/images/game/zuoqiu/bule_dot.png) no-repeat; font-size:1px}
    #scoreBoard {position:absolute; z-index:3; top:230px; left:346px; font-size:50px; color:white; filter:alpha(opacity=0); -moz-opacity:0; opacity:0}
    #tips {padding:15px 0 0 20px; text-align:left; color:red; font-size:12px}
</style>
<script type="text/javascript">
        // common 
    function $(str) {
    	return document.getElementById(str);
    }
    function $tag(str,target) {
    	target = target || document;
    	return target.getElementsByTagName(str);
    }
    function addEventHandler(obj,eType,fuc){
    	if(obj.addEventListener){ 
    		obj.addEventListener(eType,fuc,false); 
    	}else if(obj.attachEvent){ 
    		obj.attachEvent("on" + eType,fuc); 
    	}else{ 
    		obj["on" + eType] = fuc; 
    	} 
    } 
    function removeEventHandler(obj,eType,fuc){
    	if(obj.removeEventListener){ 
    		obj.removeEventListener(eType,fuc,false); 
    	}else if(obj.attachEvent){ 
    		obj.detachEvent("on" + eType,fuc); 
    	} 
    }
    function randowNum(start,end) {
    	return Math.floor(Math.random()*(end - start)) + start;
    }
    Array.prototype.remove=function(dx) {
    	if(isNaN(dx)||dx>this.length){return false;}
    	for(var i=0,n=0;i<this.length;i++)
    	{
    		if(this[i]!=this[dx])
    		{
    			this[n++]=this[i]
    		}
    	}
    	this.length-=1
    }
    //const
    var TOTALR = 15, //球的半径(包括阴影)
    	R = 12, //球真实半径
    	POKER = 20,
    	W = 736, //案宽
    	H = 480, //案高
    	THICKNESS =  32, //边缘厚度
    	RATE = 100, //刷新频率
    	F = 0.01, //摩擦力
    	LOSS = 0.2, // 碰撞速度损失
    	TIPS = ["Tip1: 参考球，目标球，目标袋，三点一线，这是最基本的进球方法","Tip2: 右下角蓝条代表击球力度，小的力度更便于控制母球位置","Tip3: 右下角白球上的蓝点控制击球点，高杆，低杆，加塞都由它控制，高手与菜鸟的区别往往在此","Tip4: 桌球，其实打的不是目标球，是母球"];
    var table, //案子
    	cueBall, //母球
    	guideBall, //参考球
    	dotWrap, //参考线
    	speed = 12,
    	rollUp = 0,
    	rollRight = 0,
    	timer,
    	forceTimer,
    	balls = [],
    	movingBalls = [],
    	pokes = [[0,0],[W/2,-5],[W,0],[0,H],[W/2,H+5],[W,H]],
    	hasShot = false;
    	shots = 0; //连击次数
    window.onload = function() {
    	initTable();
    	initShootPos();
    	showTips();
    	startGame();
    }
    function startGame() {
    	initBall();
    	addEventHandler(table,"mousemove",dragCueBall);
    	addEventHandler(table,"mouseup",setCueBall);
    }
    function initTable() {
    	table = $("table");
    	var dotWrapDiv = document.createElement("div"),
    		guideBallDiv = document.createElement("div");
    	dotWrapDiv.id = "dotWrap";
    	guideBallDiv.className = "guide ball";
    	setStyle(guideBallDiv,"display","none");
    	dotWrap = table.appendChild(dotWrapDiv);
    	guideBall = table.appendChild(guideBallDiv);
    }
    function initBall() {
    	//添加母球
    	cueBall = new Ball("cue",170,H/2);
    	balls.push(cueBall);
    	//添加目标球
    	for(var i = 0; i < 5; i++) {
    		for(var j = 0; j <= i; j++)	{
    			var ball = new Ball("target",520 + i*2*R, H/2 - R*i + j*2*R);
    			balls.push(ball);
    		}
    	}
    }
    function initShootPos() {
    	var wrap = $("shootPos"),
    		handler = $("dot"),
    		arrowR = 18;
    	addEventHandler(wrap,"mousedown",selectDot);
    	function selectDot(e) {
    		e = e || event;
    		var pos = getElemPos(wrap),
    			x = e.clientX - pos[0] - handler.offsetWidth/2,
    			y = e.clientY - pos[1] - handler.offsetHeight/2;
    		if(Math.sqrt((x-22)*(x-22) + (y-22)*(y-22)) > arrowR) {
    			var angle = Math.atan2(x-22,y-22);
    			x = arrowR*Math.sin(angle) + 22;
    			y = arrowR*Math.cos(angle) + 22;
    		}
    		setPos(handler,x,y);		
    	}
    }
    function getElemPos(target,reference) {
    	reference = reference || document;
    	var left = 0,top = 0;
    	return getPos(target);
    	function getPos(target) {
    		if(target != reference) {
    			left += target.offsetLeft;
    			top += target.offsetTop;
    			return getPos(target.parentNode);
    		} else {
    			return [left,top];
    		}
    	}
    }
    // ball class
    function Ball(type,x,y) {
    	var div = document.createElement("div");
    	div.className = type + " ball";
    	this.elem = table.appendChild(div);
    	this.type = type;
    	this.x = x; //位置
    	this.y = y;
    	this.angle = 0; //角度
    	this.v = 0; //速度(不包含方向)
    	setBallPos(this.elem,x,y);
    	return this;
    }
    function setCueBall() {
    	removeEventHandler(table,"mousemove",dragCueBall);
    	removeEventHandler(table,"mouseup",setCueBall);
    	startShot();
    }
    function startShot() {
    	show(cueBall.elem);
    	addEventHandler(table,"mousemove",showGuide);
    	addEventHandler(table,"mousedown",updateForce);
    	addEventHandler(table,"mouseup",shotCueBall);
    }
    function dragCueBall(e) {
    	var toX,toY;
    	e = e || event;
    	toX = e.clientX - table.offsetLeft - THICKNESS,
    	toY = e.clientY - table.offsetTop - THICKNESS;
    	toX = toX >= R ? toX : R;
    	toX = toX <= 170 ? toX : 170;
    	toY = toY >= R ? toY : R;
    	toY = toY <= H - R ? toY : H - R;
    	setBallPos(cueBall,toX,toY);
    }
    function shotCueBall() {
    	removeEventHandler(table,"mousemove",showGuide);
    	removeEventHandler(table,"mousedown",updateForce);
    	removeEventHandler(table,"mouseup",shotCueBall);
    	window.clearInterval(forceTimer);
    	speed = $("force").offsetWidth * 0.15;
    	var dotDisX = $("dot").offsetLeft-22,
    		dotDisY = $("dot").offsetTop-22,
    		dotDis = Math.sqrt(dotDisX*dotDisX + dotDisY*dotDisY),
    		dotAngle = Math.atan2(dotDisX,dotDisY);
    	rollRight = Math.round(dotDis*Math.sin(dotAngle))/5;
    	rollUp = -Math.round(dotDis*Math.cos(dotAngle))/5;
    	var formPos = getBallPos(cueBall.elem),
    		toPos = getBallPos(guideBall),
    		angle = Math.atan2(toPos[0] - formPos[0],toPos[1] - formPos[1]);
    	hide(dotWrap);
    	hide(guideBall);
    	cueBall.v = speed;
    	cueBall.angle = angle;
    	movingBalls.push(cueBall);
    	timer = window.setInterval(roll,1000 / RATE);
    }
    function showGuide(e) {
    	var fromX,fromY,toX,toY;
    	e = e || event;
    	toX = e.clientX - table.offsetLeft - THICKNESS,
    	toY = e.clientY - table.offsetTop - THICKNESS;
    	setBallPos(guideBall,toX,toY);
    	show(dotWrap);
    	show(guideBall);
    	drawLine();
    	//参考线
    	function drawLine() {
    		var dotNum = 16,
    			pos = getBallPos(cueBall.elem);
    		dotWrap.innerHTML = "";
    		fromX = pos[0];
    		fromY = pos[1];
    		var partX = (toX - fromX) / dotNum,
    			partY = (toY - fromY) / dotNum;
    		for(var i = 1; i < dotNum; i++) {
    			var x = fromX + partX * i,
    				y = fromY + partY * i;
    			drawDot(dotWrap, x, y);
    		}		
    	}
    }
    function roll() {
    	if(movingBalls.length <= 0) {
    		if(!hasShot) shots = 0;
    		else shots ++; //累计连击
    		hasShot = false;
    		setStyle($("force"),"width",80+"px");
    		setPos($("dot"),22,22);		
    		window.clearInterval(timer);
    		if(shots > 1) showScore(shots); //显示连击数
    		startShot();
    	}
    	for(var i = 0; i < movingBalls.length; i++) {
    		var ball = movingBalls[i],
    			sin = Math.sin(ball.angle),
    			cos = Math.cos(ball.angle);
    		ball.v -= F;
    		//移除静止的小球
    		if(Math.round(ball.v) == 0) {
    			ball.v = 0;
    			movingBalls.remove(i);
    			continue;	
    		}
    		var vx = ball.v * sin,
    			vy = ball.v * cos;
    		ball.x += vx;
    		ball.y += vy;
    		//入袋
    		if(isPocket(ball.x,ball.y)) {
    			hide(ball.elem);
    			if(ball.type == "cue") {
    					if(!hasShot) shots = 0;
    					hasShot = false;
    				window.setTimeout(function(){
    					ball.v = 0;	
    					setBallPos(ball,170,250);
    				},500);
    			}else {
    				//移除入袋小球
    				hasShot = true;
    				ball.v = 0;	
    				for(var k = 0, l =0; k < balls.length; k++) {
    					if(balls[k] != ball) {
    						balls[l++] = balls[k];
    					}
    				}
    				balls.length -= 1;
    			}
    			return;
    		}
    		//边缘碰撞
    		if(ball.x < R || ball.x > W - R) {
    			ball.angle *= -1;
    			ball.angle %= Math.PI;
    			ball.v = ball.v * (1 - LOSS);
    			vx = ball.v*Math.sin(ball.angle);
    			vy = ball.v*Math.cos(ball.angle);
    			if(ball.x < R) ball.x = R;
    			if(ball.x > W - R) ball.x = W - R;
    			//母球加塞
    			if(ball.type == "cue")	{
    				if(ball.angle > 0) vy -= rollRight;
    				else vy += rollRight;
    				vx += rollUp;
    				rollUp *= 0.2;
    				rollRight *= 0.2;
    				ball.v = Math.sqrt(vx*vx + vy*vy);
    				ball.angle = Math.atan2(vx,vy);
    			}				
    		}
    		if(ball.y < R || ball.y > H - R) {
    			ball.angle = ball.angle > 0 ? Math.PI - ball.angle : - Math.PI - ball.angle ;
    			ball.angle %= Math.PI;
    			ball.v = ball.v * (1 - LOSS);
    			vx = ball.v*Math.sin(ball.angle);
    			vy = ball.v*Math.cos(ball.angle);
    			if(ball.y < R) ball.y = R;
    			if(ball.y > H - R) ball.y = H - R;	
    			//母球加塞
    			if(ball.type == "cue")	{
    				if(Math.abs(ball.angle) < Math.PI/2) vx += rollRight;
    				else vx -= rollRight;
    				vy += rollUp;
    				rollUp *= 0.2;
    				rollRight *= 0.2;
    				ball.v = Math.sqrt(vx*vx + vy*vy);
    				ball.angle = Math.atan2(vx,vy);
    			}					
    		}
    		//小球碰撞
    		for(var j = 0; j < balls.length; j++) {
    			var obj = balls[j];
    			if(obj == ball) continue;
    			var disX = obj.x - ball.x,
    				disY = obj.y - ball.y,
    				gap = 2 * R;
    			if(disX <= gap && disY <= gap) {
    				var dis = Math.sqrt(Math.pow(disX,2)+Math.pow(disY,2));
    				if(dis <= gap) {
    					//如果是静止的，则添加到数组movingBalls
    					if(Math.round(obj.v) == 0)	
    					movingBalls.push(obj);
    					//将坐标旋转到x轴进行碰撞计算
    					// 计算角度和正余弦值 - 精确值
    					//var c = (obj.x*ball.y - obj.y*ball.x)/(2*R),
    					//	d = Math.sqrt(ball.x*ball.x + ball.y*ball.y),
    					//	angle = Math.asin(ball.y/d) - Math.asin(c/d) - ball.angle%(Math.PI/2),
    						//angle =  Math.asin(oy / (2 * R)),
    					//还原两球相切状态 - 近似值
    					ball.x -= (gap - dis)*sin;
    					ball.y -= (gap - dis)*cos;
    					disX = obj.x - ball.x;
    					disY = obj.y - ball.y;
    					// 计算角度和正余弦值
    					var angle = Math.atan2(disY, disX),
    						hitsin = Math.sin(angle),
    						hitcos = Math.cos(angle),
    						objVx = obj.v * Math.sin(obj.angle),
    						objVy = obj.v * Math.cos(obj.angle);
    						//trace(angle*180/Math.PI);
    					// 旋转坐标
    					var x1 = 0,
    						y1 = 0,
    						x2 = disX * hitcos + disY * hitsin,
    						y2 = disY * hitcos - disX * hitsin,
    						vx1 = vx * hitcos + vy * hitsin,
    						vy1 = vy * hitcos - vx * hitsin,
    						vx2 = objVx * hitcos + objVy * hitsin,
    						vy2 = objVy * hitcos - objVx * hitsin;
    					// 碰撞后的速度和位置
    					var plusVx = vx1 - vx2;
    					vx1 = vx2;
    					vx2 = plusVx + vx1;
    					//母球加塞
    					if(ball.type == "cue")	{
    						vx1 += rollUp;
    						rollUp *= 0.2;
    					}				
    					x1 += vx1;
    					x2 += vx2;
    					// 将位置旋转回来
    					var x1Final = x1 * hitcos - y1 * hitsin,
    						y1Final = y1 * hitcos + x1 * hitsin,
    						x2Final = x2 * hitcos - y2 * hitsin,
    						y2Final = y2 * hitcos + x2 * hitsin;
    					obj.x = ball.x + x2Final;
    					obj.y = ball.y + y2Final;
    					ball.x = ball.x + x1Final;
    					ball.y = ball.y + y1Final;
    					// 将速度旋转回来
    					vx = vx1 * hitcos - vy1 * hitsin;
    					vy = vy1 * hitcos + vx1 * hitsin;
    					objVx = vx2 * hitcos - vy2 * hitsin;
    					objVy = vy2 * hitcos + vx2 * hitsin; 
    					//最终速度
    					ball.v = Math.sqrt(vx*vx + vy*vy) * (1 - 0);
    					obj.v = Math.sqrt(objVx*objVx + objVy*objVy) * (1 - 0);
    					// 计算角度
    					ball.angle = Math.atan2(vx , vy);
    					obj.angle = Math.atan2(objVx , objVy);	
    					//break;
    				}
    			}
    		}
    		setBallPos(ball,ball.x,ball.y);	
    	}
    }
    function isPocket(x,y) {
    	if(y < POKER) return check(0,2);
    	else if (y > H - POKER) return check(3,5);
    	else return false;
    	function check(m,n) {
    		for(var i=m; i<=n; i++) {
    			if(x >= pokes[i][0] - POKER && x <= pokes[i][0] + POKER) {
    				var dis = Math.sqrt(Math.pow(x - pokes[i][0],2) + Math.pow(y - pokes[i][1],2));
    				if(dis <= POKER) return true;
    				else return false;
    			}
    		}	
    	} 
    }
    function getBallPos(obj) {
    	var pos = [];
    	pos.push(obj.offsetLeft - THICKNESS + TOTALR);
    	pos.push(obj.offsetTop - THICKNESS + TOTALR);
    	return pos;
    }
    function setPos(obj,x,y) {
    	obj.style.left = x + "px";
    	obj.style.top = y + "px";
    }
    function setBallPos(ball,x,y) {
    	if(ball.constructor == Ball) {
    		ball.x = x;
    		ball.y = y;
    		ball = ball.elem;
    	}
    	setPos(ball,x + THICKNESS - TOTALR,y + THICKNESS - TOTALR);
    }
    function drawDot(wrap,x,y) {
    	var elem = document.createElement("div");
    	setStyle(elem,{
    		position: "absolute",
    		width: "1px",
    		height: "1px",
    		fontSize: "1px",
    		background: "white"
    	});
    	setPos(elem,x,y);
    	wrap.appendChild(elem);
    }
    function updateForce() {
    	var obj = $("force"),
    		len = 80,
    		up = true;
    	forceTimer = window.setInterval(update,10);
    	function update() {
    		 if(up) setStyle(obj,"width",len+++"px");
    		 else setStyle(obj,"width",len--+"px");
    		 if(len > 136) up = false;
    		 if(len <= 0) up = true;
    	}
    }
    function setStyle() {
    	if(arguments.length == 2 &&  typeof arguments[1] == "object") {
    		for(var key in arguments[1]) {
    			arguments[0].style[key] = arguments[1][key];
    		}
    	} else if (arguments.length > 2) {
    		arguments[0].style[arguments[1]] = arguments[2];
    	}
    }
    function hide(obj) {
    	setStyle(obj,"display","none");
    }
    function show(obj) {
    	setStyle(obj,"display","block");
    }
    //输出信息
    function trace(sth,who) {
    	who = who || $("tips");
    	if(document.all) who.innerText = sth;
    	else who.textContent = sth;
    	return who;
    }
    function showScore(n) {
    	var wrap = $("scoreBoard");
    	trace(n+"连杆",wrap);
    	fadeIn(wrap);
    }
    function fadeIn(obj){
    	var fromY = 230,
    		posStep = [8,14,19,23,26,28,29,29,30,30,30],
    		opaStep = [0,0.05,0.1,0.15,0.2,0.25,0.3,0.4,0.5,0.6,0.8],
    		fromOpa = 0,
    		t = 0,
    		step = posStep.length,
    		inTimer = window.setInterval(showIn,20),
    		outTimer;
    	function showIn() {
    		setOpacity(obj,opaStep[t]);
    		obj.style.top = fromY + posStep[t] + "px";
    		t++;
    		if(t>=step) {
    			window.clearInterval(inTimer);
    			outTimer = window.setInterval(fadeOut,50);
    		}	
    	}
    	function fadeOut() {
    		t--;
    		setOpacity(obj,opaStep[t]);
    		obj.style.top = fromY + posStep[t] + "px";
    		if(t <= 0) {
    			window.clearInterval(outTimer);
    			hide(obj);
    		}
    	}
    }
    function setOpacity(obj,n) {
    	obj.style.cssText = "filter:alpha(opacity="+ n*100 +"); -moz-opacity:"+ n +"; opacity:"+ n;
    }
    function showTips() {
    	var i = 0;
    	tip();
    	window.setInterval(tip,3000);
    	function tip() {
    		trace(TIPS[i++]);
    		if(i >= TIPS.length) i = 0;
    	}
    }
    </script>
</head>
<body>
    <div id="table">
        <div id="scoreBoard"></div>
    </div>
    <div class="bot">
        <div id="tips"></div>
        <div class="ctrl">
            <div id="force"></div>
            <div id="shootPos">
                <div id="dot"></div>
            </div>
        </div>
    </div>
</body>

      </article>
    </section>

    

    

    
  </div>
</div>


            <footer class="ui basic center aligned segment" style="background-color: transparent;">
              
              <p>© 2020 - 2021 俊樹&#39;s Miscellaneous</p>
              
            
            
            <script type="text/javascript"> 
              if(window.console) {
	              var cons = console; 
	              if(cons) { 
		              cons.group("Hey hey hey👀！");
		              cons.info("👋🏻Hi there, YES IT'S YOU, watching my source code yea?！I'm watching you🖕🏻 https://ashao0425.github.io/"); 
		              cons.log("%c俊樹's Miscellaneous", "background-image: linear-gradient(#063053, #395873, #5c7c99);font-size: 2rem;");
		              cons.info("==============================Splitting Line==============================");
		              cons.log("  █████▒█    ██  ▄████▄   ██ ▄█▀       ██████╗ ██╗   ██╗ ██████╗\n▓██   ▒ ██  ▓██▒▒██▀ ▀█   ██▄█▒        ██╔══██╗██║   ██║██╔════╝\n▒████ ░▓██  ▒██░▒▓█    ▄ ▓███▄░        ██████╔╝██║   ██║██║  ███╗\n░▓█▒  ░▓▓█  ░██░▒▓▓▄ ▄██▒▓██ █▄        ██╔══██╗██║   ██║██║   ██║\n░▒█░   ▒▒█████▓ ▒ ▓███▀ ░▒██▒ █▄       ██████╔╝╚██████╔╝╚██████╔╝\n ▒ ░   ░▒▓▒ ▒ ▒ ░ ░▒ ▒  ░▒ ▒▒ ▓▒       ╚═════╝  ╚═════╝  ╚═════╝\n ░     ░░▒░ ░ ░   ░  ▒   ░ ░▒ ▒░\n ░ ░    ░░░ ░ ░ ░        ░ ░░ ░\n          ░     ░ ░      ░  ░\n")
		              cons.groupEnd();
	              } 
              }
              </script>
              
			        
              <center>
                <script async src="/js/busuanzi.pure.mini.js"></script>
				        👀Site views: <span style="color:seagreen"><span id="busuanzi_value_site_pv"></span></span> times
              </center>
              
			        
              <center>
                👶Site age: <SPAN id=span_dt_dt style="color: #2E8B57;"></SPAN>
                <SCRIPT language=javascript>
                function show_date_time(){
                window.setTimeout("show_date_time()", 1000);
                BirthDay=new Date("9/5/2021 02:14:49");
                today=new Date();
                timeold=(today.getTime()-BirthDay.getTime());
                sectimeold=timeold/1000
                secondsold=Math.floor(sectimeold);
                msPerDay=24*60*60*1000
                e_daysold=timeold/msPerDay
                daysold=Math.floor(e_daysold);
                e_hrsold=(e_daysold-daysold)*24;
                hrsold=Math.floor(e_hrsold);
                e_minsold=(e_hrsold-hrsold)*60;
                minsold=Math.floor((e_hrsold-hrsold)*60);
                seconds=Math.floor((e_minsold-minsold)*60);
                span_dt_dt.innerHTML=""+daysold+" "+"days"+" "+hrsold+" "+"hours"+" "+minsold+" "+"minutes"+" "+seconds+" "+"seconds";
                }
                show_date_time();
                </SCRIPT>
              </center>
              
              
              
              
            </footer>
          </div>
        </section>
        <section class="back">
          <div class="dream-max-width">
            <header class="ui basic very padded segment dream-header">
  
  <div class="ui small circular image">
    <img src="/avatar/Avatar3.jpg" alt="avatar" />
  </div>
  

  

  <div class="content">
    <h1 class="ui medium header">俊樹&#39;s Miscellaneous<span class="sub header"><div id="binft"></div><script>var binft=function(t){function r(){return f[Math.floor(Math.random()*f.length)]}function e(){return String.fromCharCode(94*Math.random()+33)}function n(t){for(var n=document.createDocumentFragment(),i=0;t>i;i++){var l=document.createElement("span");l.textContent=e(),l.style.color=r(),n.appendChild(l)}return n}function i(){var r=a[c.skillI];c.step?c.step--:(c.step=o,c.prefixP<l.length?(c.prefixP>=0&&(c.text+=l[c.prefixP]),c.prefixP++):"forward"===c.direction?c.skillP<r.length?(c.text+=r[c.skillP],c.skillP++):c.delay?c.delay--:(c.direction="backward",c.delay=g):c.skillP>0?(c.text=c.text.slice(0,-1),c.skillP--):(c.skillI=(c.skillI+1)%a.length,c.direction="forward")),t.textContent=c.text,t.appendChild(n(c.prefixP<l.length?Math.min(b,b+c.prefixP):Math.min(b,r.length-c.skillP))),setTimeout(i,d)}var l="",a=["Lover of Mathematics and Science."].map(function(t){return t+""}),g=2,o=1,b=5,d=75,f=["rgb(110,64,170)","rgb(150,61,179)","rgb(191,60,175)","rgb(228,65,157)","rgb(254,75,131)","rgb(255,94,99)","rgb(255,120,71)","rgb(251,150,51)","rgb(226,183,47)","rgb(198,214,60)","rgb(175,240,91)","rgb(127,246,88)","rgb(82,246,103)","rgb(48,239,130)","rgb(29,223,163)","rgb(26,199,194)","rgb(35,171,216)","rgb(54,140,225)","rgb(76,110,219)","rgb(96,84,200)"],c={text:"",prefixP:-b,skillI:0,skillP:0,direction:"forward",delay:g,step:o};i()};binft(document.getElementById("binft"));</script></span>
    </h1>

    <article class="ui horizontal list">
      
      <a class="item" href="/posts">
        <i class="archive icon" title="Archives"></i>
      </a>
      
      <a class="item" href="/categories">
        <i class="th list icon" title="All Categories"></i>
      </a>
      <a class="item" href="/tags">
        <i class="tags icon" title="All Tags"></i>
      </a>
    </article>

    
    
    
    
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
    

    

    
    
    
          <div class="dream-tags">
          
          
          
            <a class="ui label" href="/tags/bash/" title="Bash">
              Bash
            </a>
          
          
          
            <a class="ui label" href="/tags/code/" title="Code">
              Code
            </a>
          
          
          
            <a class="ui label" href="/tags/game/" title="Game">
              Game
            </a>
          
          
          
            <a class="ui label" href="/tags/git/" title="Git">
              Git
            </a>
          
          
          
            <a class="ui label" href="/tags/github/" title="Github">
              Github
            </a>
          
          
          
            <a class="ui label" href="/tags/gravity/" title="Gravity">
              Gravity
            </a>
          
          
          
            <a class="ui label" href="/tags/html/" title="Html">
              Html
            </a>
          
          
          
            <a class="ui label" href="/tags/hugo/" title="Hugo">
              Hugo
            </a>
          
          
          
            <a class="ui label" href="/tags/js/" title="Js">
              Js
            </a>
          
          
          
            <a class="ui label" href="/tags/latex/" title="LaTeX">
              LaTeX
            </a>
          
          
          
            <a class="ui label" href="/tags/mathematics/" title="Mathematics">
              Mathematics
            </a>
          
          
          
            <a class="ui label" href="/tags/mathjax/" title="MathJax">
              MathJax
            </a>
          
          
          
            <a class="ui label" href="/tags/ssh-key/" title="SSH Key">
              SSH Key
            </a>
          
          
          
            <a class="ui label" href="/tags/tutorial/" title="Tutorial">
              Tutorial
            </a>
          
          
          
            <a class="ui label" href="/tags/website/" title="Website">
              Website
            </a>
          
          </div>
    

    
  </div>

  
  <script src="/js/sweetalert.min.js"></script> 
  <link rel="stylesheet" href="/css/sweetalert.css" type='text/css' media='all' />
</header>

<script>document.body.oncopy = function() {swal("Copied successfully！", "If you would you like to use this site, please attribute or indicate the source if authorized！","success");};</script>

<div class="ui relaxed grid dream-grid dream-back">
  
  
  
  <div class="sixteen wide mobile eight wide tablet four wide computer column dream-column">
    <article class="ui segment markdown-body">
      <div class="ui medium header">Bio 👋</div>
      <ul>
<li><strong>👨Names</strong>:
<ul>
<li>English: Alex Shao</li>
<li>中文: 邵宪辉</li>
<li>日本語：安田俊樹</li>
</ul>
</li>
<li><strong>👀Age</strong>: 16, 2005/4/25</li>
<li><strong>🏫School</strong>: SLAS (shittiest school ever)</li>
<li><strong>❤️Interests</strong>: Python, Html, Java, Js, Anime(especially &ldquo;ダンジョンに出会いを求めるのは間違っているだろうか&rdquo;), Math, Science, Sleep, Diarreah &amp; Constipation (Well, I had stomache issue since I was born, innate), bikes</li>
<li><strong>🚩Nationality</strong>: Chinese &amp; Japanese (Microsoft somehow does not support country flag emojis&hellip;)</li>
<li><strong>💼Occupation</strong>: Student</li>
<li><strong>📺Movies</strong>: No movies, animes only, &ldquo;ダンジョンに出会いを求めるのは間違っているだろうか&rdquo;</li>
<li><strong>📫Email</strong>: <a href="mailto:alex2005@gmail.com">alex2005@gmail.com</a></li>
<li><strong>👨‍🏫Values</strong>: Constrain impetuosity</li>
<li><strong>🐧QQ</strong>: 1959796501 (Also contact my QQ besides mail)</li>
<li><strong>💻Device</strong>: Huawei Matebook 14, 2019</li>
<li><strong>🖱️IDE</strong>: VsCode</li>
</ul>

    </article>
  </div>
  
  <div class="sixteen wide mobile eight wide tablet four wide computer column dream-column">
    <article class="ui segment markdown-body">
      <div class="ui medium header">Acknowledgments</div>
      <ul>
<li><strong>Vansh Kamleshbhai Padaliya</strong>: Always helping and assisting with no doubts and hesitations, good buddy, known for 3 years.</li>
<li><strong>吴思萌 Mónica</strong>: An elder sister, always accompanying and encouraging, deskmate in previous school, known for 5 years.</li>
<li><strong>姚轶膑</strong>: Great buddy as well, spent time screwing out often, always encouraging, known for 5 years.</li>
<li><strong>Koki Kin</strong>: Typical Japanese Otaku, still a great buddy, known for 1.5 years, giving help when I need.</li>
<li><strong>Semih Deli</strong>: Known since 2, developed this site together.</li>
<li>All the others people who answered my requests I pulled on Github when I met problems.</li>
</ul>

    </article>
  </div>
  

  <div class="sixteen wide mobile eight wide tablet four wide computer column dream-column">
    <article class="ui segment">
      <div class="ui medium header">Social Links</div>
      <nav class="ui secondary menu dream-menu dream-socials">
  
  <a class="item" href="/index.xml">
    <i class="large rss square icon" title="RSS"></i>
  </a>
  

  
  <a class="item" href="mailto:AlexShao20050425@163.com">
    <i class="large mail icon" title="Email"></i>
  </a>
  

  

  

  

  

  

  

  

  

  
  
  
    <a class="item" href="https://github.com/ashao0425" target="_blank">
      <i class="large github icon" title="GitHub"></i>
    </a>
  
  
</nav>

    </article>
  </div>

  <div class="sixteen wide mobile eight wide tablet four wide computer column dream-column">
    
    <article class="ui segment">
      <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.
    </article>
    
  </div>

  
</div>

          </div>
        </section>
      </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0"></script>
    <script src="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.js"></script>

    
    <div class="ui segment" id="dream-search">
  <div class="ui search">
    <div class="ui transparent input">
      <input class="prompt" type="text" placeholder="Search" />
    </div>
    <div class="results"></div>
  </div>
</div>
<script>
  $(document).ready(function () {
    $.getJSON('https:\/\/AShao0425.github.io\//index.json', function (data) {
      $('.ui.search').search({
        source: data,
        searchFields: ['title'],
        showNoResults: false,
      })
    })
  })
</script>
<script src="/js/search.js"></script>

    

    

    <script>
  window.background = "/background/back1.png"
  window.defaultDark =  null 
  window.backgroundDark = "/background/BackgroundBlack.jpg"
  window.backgroundImageDark = "/background/BackgroundBlack.jpg"
  window.darkNav =  true 
  window.maxTags =  null 
  window.hasTwitterEmbed =  null 
  window.fixedNav =  true 

  if (window.hasTwitterEmbed) {
    
    window.twttr = (function (d, s, id) {
      var js,
        fjs = d.getElementsByTagName(s)[0],
        t = window.twttr || {}
      if (d.getElementById(id)) return t
      js = d.createElement(s)
      js.id = id
      js.src = 'https://platform.twitter.com/widgets.js'
      fjs.parentNode.insertBefore(js, fjs)

      t._e = []
      t.ready = function (f) {
        t._e.push(f)
      }

      return t
    })(document, 'script', 'twitter-wjs')
  }
</script>
<script src="https://cdn.jsdelivr.net/npm/overlayscrollbars@1.13.1/js/jquery.overlayScrollbars.min.js"></script>
<script src="/js/header.js"></script>
<script src="/js/main.js"></script>
<script src="/js/theme.js"></script>

    


<script src="https://cdn.jsdelivr.net/npm/luxon@1.26.0"></script>

<script>
  format()

  function format() {
    $('span[data-format="luxon"]').each(function () {
      var date = $(this).text()

      $(this).text(luxon.DateTime.fromISO(date, { locale: "en" }).toFormat("yyyy/MM/dd"))
    })
  }
</script>



<script src="/js/scrollToTop.js"></script>


<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js"></script>



<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/clojure.min.js"></script>

<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/ocaml.min.js"></script>



<script>
  hljs.highlightAll()
  setHighlightTheme()

  function setHighlightTheme() {
    var isDark = localStore.getItem('hugo-theme-dream-is-dark')
    isDark = isDark ? isDark : window.defaultDark ? 'y' : isDark

    var lightTheme = "tomorrow"
    var darkTheme = "tomorrow-night"
    var theme = isDark === 'y' ? darkTheme : lightTheme

    $('link[data-highlight]').attr('href', 'https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/' + theme + '.min.css')
    $('pre').css('background', isDark === 'y' ? '#333' : '')
  }
</script>



<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.0.0-rc.1"></script>
<script src="/js/post.js" defer></script>


    

    
    
<script type="application/javascript">
var doNotTrack = false;
if (!doNotTrack) {
	window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
	ga('create', 'UA-206749728-1', 'auto');
	
	ga('send', 'pageview');
}
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>

    
	
	
    <div id="landlord">
      <div class="message" style="opacity:0"></div>
      <canvas id="live2d" width="280" height="250" class="live2d"></canvas>
      <div class="hide-button">Hide</div>
    </div>
    
	
    <script type="text/javascript">
      var message_Path = '/live2d/'
      var home_Path = 'https://ashao0425.github.io/'  <!--Edit the domain into yours here-->
    </script>
    <script type="text/javascript" src="/live2d/js/live2d.js"></script>
    <script type="text/javascript" src="/live2d/js/message.js"></script>
    <script type="text/javascript">
      loadlive2d("live2d", "/live2d/model/tia/model.json");
    </script>
  </body>

  
  
  
	
    <canvas class="fireworks" style="position: fixed;left: 0;top: 0;z-index: 1; pointer-events: none;" ></canvas> 
    <script type="text/javascript" src="/js/anime.min.js"></script> 
    <script type="text/javascript" src="/js/fireworks.js"></script>    
</html>
